# encoding=utf-8

import asyncio
from email.policy import default
from genericpath import isfile
from matplotlib.style import context
import requests #导入requests模块
import json
import time
import datetime
from openpyxl import load_workbook, Workbook
import openpyxl
import os, sys
import yaml
from dataclasses import dataclass, field
from tqdm import tqdm
import warnings

# 获取特殊日期
def get_special_date():
    ct = datetime.datetime.now()
    year = ct.year
    month = ct.month
    day = ct.day
    m = ""
    d = ""
    if month < 10:
        m = f"0{month}"
    else:
        m = f"{month}"
    if day < 10:
        d = f"0{day}"
    else:
        d = f"{day}"
    ds = f"{m}/{d}/{year}"
    return ds


def get_line(sheet, line_index):
    num_rows = sheet.max_row
    num_cols = sheet.max_column
    line = []
    for c in range(1, num_cols + 1):
        v = sheet.cell(line_index, c).value
        line.append(v)
    return line


@dataclass
class download_context:
    cookie: str = field(default="")           # cookie 验证信息
    token: str = field(default="")            # token  验证信息
    vin_excel_path: str = field(default="")   # vin路径
    vin_excel_sheet: str = field(default="")  # vin excel sheet
    merge_excel_path: str = field(default="") # 合并excel的路径
    merge_excel_name: str = field(default="") # 合并excel的名字
    merge_excel_sheet: str = field(default="") # 合并excel的sheet
    today: str = field(default="")            # 今天
    concurrent: int = field(default=15)       # 并发度
    fini_item_queue: None = field(default=None) # 完成下载队列

    def update(self):
        if "" == self.token:
            self.update_token()
        if "" == self.today:
            self.today = get_special_date()
        if "" == self.merge_excel_name:
            self.merge_excel_name = "merger.xlsx"

    # 更新token
    def update_token(self):
        return
        url = "https://cc1.10646.cn//provision/api/v1/csrfToken/refresh"
        header = {}
        header["Cookie"] = self.cookie
        resp = requests.get(url=url, headers=header)
        if 200 != resp.status_code:
            print(f"error: update token failed, http code {resp.status_code}")
            sys.exit(-1)
            return
        self.token = resp.text
        # print(f"update token: {self.token}")
        return self.token
        
# 构造上下文
def make_download_context():
    # 加载配置文件
    config_path = "./config.yaml"
    with open(config_path, "r", encoding="utf-8") as f:
        data = f.read()
    # result = yaml.load(data, Loader=yaml.FullLoader)
    result = {}
    cookie = ""
    token = ""
    vin_excel_path = ""
    vin_excel_sheet = ""
    merge_excel_path = ""
    merge_excel_name = "merger_20220408.xlsx"
    merge_excel_sheet = "Sheet0"
    today = ""
    concurrent = 0
    if "cookie" in result.keys():
        cookie = result["cookie"]
    if "token" in result.keys():
        token = result["token"]
    if "vin_excel_path" in result.keys():
        vin_excel_path = result["vin_excel_path"]
    if "vin_excel_sheet" in result.keys():
        vin_excel_sheet = result["vin_excel_sheet"]
    if "merge_excel_path" in result.keys():
        merge_excel_path = result["merge_excel_path"]
    if "merge_excel_name" in result.keys():
        merge_excel_name = result["merge_excel_name"]
    if "merge_excel_sheet" in result.keys():
        merge_excel_sheet = result["merge_excel_sheet"]
    if "today" in result.keys():
        today = result["today"]
    if "concurrent" in result.keys():
        concurrent = result["concurrent"]
        if concurrent < 1:
            concurrent = 1
    # 检查是否存在合并目录
    exist = os.path.exists(merge_excel_path)
    if not exist:
        os.makedirs(merge_excel_path)

    ctx = download_context(cookie=cookie, token=token, 
        vin_excel_path=vin_excel_path, vin_excel_sheet=vin_excel_sheet,
        merge_excel_path=merge_excel_path, merge_excel_name=merge_excel_name, 
        merge_excel_sheet=merge_excel_sheet, today=today,
        concurrent=concurrent)
    ctx.update()
    return ctx



@dataclass
class sim_download:
    context: download_context
    now_ms: int = field(init=False, default=0)         # 毫秒时间戳
    now_ms_str: str = field(init=False, default="0")     # 毫秒时间戳字符串
    _stop: bool = field(init=False, default=False)
    active_task_count: int = field(init=False, default=1)  # 有效任务总数
    finished_progress_bar: tqdm = field(init = False, default=tqdm(total=1)) # 完成进度条

    # 获取当前毫秒时间戳
    def _now_ms(self):
        return self.now_ms

    # 获取当前毫秒时间戳
    def _now_ms_str(self):
        return self.now_ms_str

    # 任务停止
    async def stop(self):
        await self.context.fini_item_queue.join()
        self._stop = True
        self.context.fini_item_queue.put_nowait(None)

    # 更新
    def update(self):
        t = time.time()
        self.now_ms = int(round(t * 1000))
        self.now_ms_str = str(self.now_ms)
        # print(self.now_ms)
        # print(self.now_ms_str)

    # 开始下载
    def on_starting_download(self, task_count):
        self.active_task_count = task_count
        self.finished_progress_bar.total = self.active_task_count
        self.finished_progress_bar.set_description_str("正在下载中")

    # 下载完成
    def on_finished_download(self):
        self.finished_progress_bar.set_description_str("下载完成")

    # 开始合并文件
    def on_starting_merge(self):
        self.finished_progress_bar.set_description_str("正在合并文件,持久化写入中")

    # 合并文件完成
    def on_finished_merge(self):
        self.finished_progress_bar.set_description_str("合并文件持久化完成")

    # 任务完成
    def on_task_finished(self):
        self.finished_progress_bar.update(n = 1)

    # 异步循环任务
    async def timer_task(self):
        while not self._stop:
            await asyncio.sleep(0.1)
            self.update()
        self.on_task_finished()


    # 加载vin列表
    def load_vin_list(self):
        count = 0
        ignore_list = []
        excel_path = self.context.vin_excel_path
        excel_sheet = self.context.vin_excel_sheet
        # 检查文件是否存在
        valid = isfile(excel_path)
        if not valid:
            print(f"error: not exist the file that {excel_path}")
            sys.exit(-1)
        wb = load_workbook(excel_path)
        sheet_list = wb.sheetnames
        # 检查是否存在这个sheet
        if excel_sheet not in sheet_list:
            wb.close()
            print(f"error: not exist the sheet \"{excel_sheet}\" in the excel")
            sys.exit(-1)
        sheet = wb[excel_sheet]
        num_rows = sheet.max_row
        vin_list = []
        for r in range(2, num_rows + 1):
            vin = sheet.cell(r, 1).value
            if vin in ignore_list:
                continue
            count += 1
            vin_list.append(vin)
        if 0 == len(vin_list):
            wb.close()
            print(f"error: vin is empty in the sheet")
            sys.exit(-1)
        return vin_list



    # 临时文件 合并
    def temp_file_merge(self):
        merge_dir = self.context.merge_excel_path
        # 找出需要合并的文件
        all_file_names = os.listdir(merge_dir)
        need_files = []
        for f in tqdm(all_file_names, desc="正在加载要合并的文件"):
            need_files.append(f"{merge_dir}/{f}")
        # 找title
        title = []
        for fp in need_files:
            wb = load_workbook(fp)
            sheet = wb["Sheet0"]
            num_rows = sheet.max_row
            if num_rows < 2:
                wb.close()
                continue
            title = get_line(sheet, 1)
            wb.close()
            break
        rows = []
        rows.append(title)

        for fp in tqdm(need_files, desc="正在合并文件"):
            wb = load_workbook(fp)
            sheet = wb["Sheet0"]
            num_rows = sheet.max_row
            num_cols = sheet.max_column
            if num_rows < 2:
                wb.close()
                continue
            for r in range(2, num_rows + 1):
                row = get_line(sheet, r)
                rows.append(row)
            wb.close()

        print("请不要退出, 正在写入文件, 稍等")
        wb = Workbook()
        ws = wb.active
        ws.title = self.context.merge_excel_sheet
        for r in rows:
            ws.append(r)
        save_path = f"{merge_dir}/{self.context.merge_excel_name}"
        wb.save(save_path)


if __name__=="__main__":
    warnings.filterwarnings('ignore')
    ctx = make_download_context()
    sim_down = sim_download(context=ctx)
    sim_down.temp_file_merge()

